namespace TfsReportRenderer.CommandLine
{
    using System;

    /// <summary>
    /// The strong typed column definition.
    /// </summary>
    /// <typeparam name="T"> The type of the property. </typeparam>
    public class ColumnDefinition<T> : ColumnDefinition
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="ColumnDefinition{T}"/> class.
        /// </summary>
        /// <param name="title"> The title of the column. </param>
        /// <param name="selector"> The selector of the property that should be placed into this column. </param>
        public ColumnDefinition(string title, Func<TestResultData, T> selector)
        {
            this.Title = title;
            this.Selector = selector;
        }

        /// <summary>
        /// Gets or sets the property selector.
        /// </summary>
        public Func<TestResultData, T> Selector { get; set; }

        public override object GetValue(TestResultData value)
        {
            return this.Selector(value);
        }
    }

    /// <summary>
    /// The column definition.
    /// </summary>
    public abstract class ColumnDefinition
    {
        /// <summary>
        /// Gets or sets the title of the column.
        /// </summary>
        public string Title { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether the values of this column should be merged when formatting the output.
        /// (When this is true, the excel formatter will merge rows of this column with identical values.)
        /// </summary>
        public bool Merge { get; set; }

        /// <summary>
        /// Creates a <see cref="ColumnDefinition{T}"/>. for a specific title and selector.
        /// </summary>
        /// <param name="title"> The title of the column. </param>
        /// <param name="selector"> The selector for the property. </param>
        /// <typeparam name="T"> The type of the property. </typeparam>
        /// <returns> The <see cref="ColumnDefinition{T}"/>. </returns>
        public static ColumnDefinition Create<T>(string title, Func<TestResultData, T> selector)
        {
            return new ColumnDefinition<T>(title, selector);
        }

        /// <summary>
        /// Executes the selector.
        /// </summary>
        /// <param name="value"> The value to extract a property from. </param>
        /// <returns> The value of the property. </returns>
        public abstract object GetValue(TestResultData value);
    }
}